<template>
  <div v-loading="loading" class="home-container" @wheel="handleWheel">
    <ul
        ref="carouselContainerRef"
        :style="{ marginTop: marginTop + 'px' }"
        class="carousel-container"
        @transitionend="handleTransitionEnd"
    >
      <li v-for="item in banners" :key="item.id">
        <CarouselItem :banner="item"></CarouselItem>
      </li>
    </ul>
    <div v-show="index > 0" class="arrow arrow-up" @click="handleSwitchTo(index - 1)">
      <Icon type="arrowUp"></Icon>
    </div>
    <div
        v-show="index < banners.length - 1"
        class="arrow arrow-down"
        @click="handleSwitchTo(index + 1)"
    >
      <Icon type="arrowDown"></Icon>
    </div>
    <ul class="dot-container">
      <li
          v-for="(item, i) in banners"
          :key="item.id"
          :class="{ active: index === i }"
          class="dot-item"
          @click="handleSwitchTo(i)"
      ></li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import { getBanner } from '@/api/banner'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import CarouselItem from './CarouselItem.vue'
import Icon from '@/components/Icon/index.vue'
import { useFetchData } from '@/hooks/useFetchData'

const index = ref(0)
const carouselContainerRef = ref<HTMLElement>()
const containerHeight = ref(0)
const switching = ref(false)

const marginTop = computed(() => -index.value * containerHeight.value)

const { data: banners, loading } = useFetchData<any[]>({
  defaultValue: [],
  fetchData: async () => await getBanner().then((res) => res.data)
})

onMounted(async () => {
  if (carouselContainerRef.value) {
    containerHeight.value = carouselContainerRef.value?.clientHeight
  }
  window.addEventListener('resize', handleResize)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
})

const handleResize = () => {
  if (carouselContainerRef.value) {
    containerHeight.value = carouselContainerRef.value?.clientHeight
  }
}

const handleSwitchTo = (i: number) => {
  index.value = i
}

const handleWheel = (e: WheelEvent) => {
  if (switching.value) return
  if (e.deltaY > 5 && index.value < banners.value.length - 1) {
    switching.value = true
    index.value++
  } else if (e.deltaY < -5 && index.value > 0) {
    switching.value = true
    index.value--
  }
}

const handleTransitionEnd = () => {
  switching.value = false
}
</script>
<style lang="less" scoped>
@import '@/styles/mixin.less';
@import '@/styles/var.less';

.home-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;

  // 测试
  // width: 60%;
  // height: 40%;
  // overflow: visible;
  // border: 2px solid #008c8c;
  // margin: 100px auto;
}

.carousel-container {
  width: 100%;
  height: 100%;
  transition: 0.3s;

  li {
    width: 100%;
    height: 100%;
  }
}

.arrow {
  .self-center();
  font-size: 22px;
  color: @gray;
  cursor: pointer;
  transform: translateX(-50%);
  @gap: 25px;

  &-up {
    top: @gap;
    transform: translate(-50%, 0);
    animation: jump-up 2s infinite;
  }

  &-down {
    top: auto;
    bottom: @gap;
    transform: translate(-50%, 0);
    animation: jump-down 2s infinite;
  }

  @jump: 10px;
  @keyframes jump-up {
    0% {
      transform: translate(-50%, @jump);
    }

    50% {
      transform: translate(-50%, -@jump);
    }

    100% {
      transform: translate(-50%, @jump);
    }
  }

  @keyframes jump-down {
    0% {
      transform: translate(-50%, -@jump);
    }

    50% {
      transform: translate(-50%, @jump);
    }

    100% {
      transform: translate(-50%, -@jump);
    }
  }
}

.dot-container {
  .self-center();
  transform: translateY(-50%);
  left: auto;
  right: 20px;
}

.dot-item {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid #fff;
  background: @words;
  cursor: pointer;
  margin-bottom: 10px;

  &.active {
    background-color: #fff;
  }
}
</style>